package cn.study.concurrenttools.stampedlock;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.StampedLock;

/**
 * @Author     ：跟大家一起学架构
 * @Description：对比ReentrantReadWriteLock 与 StampedLock性能
 */
public class StampedAndRWLockComp {
    private static final StampedLock stampedLock = new StampedLock();

    private static final ReadWriteLock lock = new ReentrantReadWriteLock();
    private static final Lock readLock = lock.readLock();//读锁

    private static int value;

    public static void main(String[] args) throws InterruptedException {

//        CountDownLatch rwLatch = new CountDownLatch(4000);
//        CountDownLatch rwCount = new CountDownLatch(4000);
//        long time = System.currentTimeMillis();
//        for(int i = 0;i<4000;i++){
//            new Thread(()->{
//                try {
//                    rwLatch.await();
//                } catch (InterruptedException e) {
//                    throw new RuntimeException(e);
//                }
//                getValueByRW();
//                rwCount.countDown();
//            }).start();
//            rwLatch.countDown();
//        }
//        rwCount.await();
//        System.out.println(",rw运行时间:"+ (System.currentTimeMillis()-time));
//
//        CountDownLatch stamptedLatch = new CountDownLatch(4000);
//        CountDownLatch stamptedCount = new CountDownLatch(4000);
//        long time1 = System.currentTimeMillis();
//        for(int i = 0;i<4000;i++){
//            new Thread(()->{
//                try {
//                    stamptedLatch.await();
//                } catch (InterruptedException e) {
//                    throw new RuntimeException(e);
//                }
//                getValueByStamped();
//                stamptedCount.countDown();
//            }).start();
//            stamptedLatch.countDown();
//        }
//        stamptedCount.await();
//        System.out.println(",stampted运行时间:"+ (System.currentTimeMillis()-time1));

        long time = System.currentTimeMillis();
        for (int i = 0; i < 100000; i++) {
            new Thread(()->{
                getValueByRW();
            }).start();
        }
        System.out.println(",rw运行时间:"+ (System.currentTimeMillis()-time));
    }


    public static int getValueByStamped() {
        long stamp = stampedLock.tryOptimisticRead();
        int result = value;
        if (!stampedLock.validate(stamp)) {
            stamp = stampedLock.readLock();
            try {
                result = value;
            } finally {
                stampedLock.unlockRead(stamp);
            }
        }
        return result;
    }

    public static int getValueByRW() {
        readLock.lock();
        int result = 0;
        try {
            result = value;
        } finally {
            readLock.unlock();
        }
        return result;
    }

}
